package com.jh.channel.controller;



import cn.jh.common.utils.*;


import com.jh.channel.business.FastSilverBusiness;
import com.jh.channel.pojo.fastsilver.*;
import com.jh.channel.repository.FastSilverInternalRepository;
import com.jh.channel.repository.FastSilverRepository;
import com.jh.channel.service.OutChannelService;
import com.jh.channel.util.Util;
import net.sf.json.JSONObject;
import org.apache.commons.collections.MapUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.data.domain.*;
import org.springframework.data.web.PageableDefault;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;



import static org.springframework.util.StringUtils.hasText;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;

import java.util.*;
import java.net.URI;



/**
 * @author lichengying
 */
@Controller
@EnableAutoConfiguration
public class FastSilverController {

    private Logger logger = LoggerFactory.getLogger(FastSilverController.class);

    private final FastSilverBusiness feastSilverBusiness;
    private final FastSilverRepository fastSilverRepository;
    private final FastSilverInternalRepository fastSilverInternalRepository;
    private final OutChannelService outChannelService;
    @Autowired
    private Util util;

    @Autowired
    public FastSilverController(FastSilverBusiness feastSilverBusiness,
                                FastSilverInternalRepository fastSilverInternalRepository,
                                FastSilverRepository fastSilverRepository,
                                OutChannelService outChannelService
    ) {
        this.feastSilverBusiness = feastSilverBusiness;
        this.fastSilverRepository = fastSilverRepository;
        this.fastSilverInternalRepository = fastSilverInternalRepository;
        this.outChannelService = outChannelService;
    }

    @Value("${schedule-task.on-off}")
    private String scheduleTaskOnOff;

    @Value("${fastQuick.payUrl}")
    private String payUrl;

    @Value("${fastQuick.internalUrl}")
    private String internalUrl;

    @Value("${fastQuick.key}")
    private String key;

    @Value("${fastQuick.uplodUrl}")
    private String uplodUrl;

    @Value("${fastQuick.callbackPayUrl}")
    private String callbackPayUrl;

    @Value("${fastQuick.agentId}")
    private String agentId;

    @Value("${fastQuick.queryInternalUrl}")
    private String queryInternalUrl;

    @Value("${fastQuick.queryOrderUrl}")
    private String queryOrderUrl;

    @RequestMapping(method= RequestMethod.POST,value="/v1.0/channel/fast_silver")
    public @ResponseBody
    Object fastSilverPay(FastSilverOrderView view) {
        String orderType = view.getOrderType();
        if (orderType.toUpperCase().equals("WECHAT".toUpperCase())) {
            orderType = OrderType.WEIXIN.getI18nCode();
        } else {
            orderType = OrderType.ALIPAY.getI18nCode();
        }
        view.setOrderType(orderType);
        FastSilverOrder order = view.transform();
        order.setMerchantName(view.getMerchantName());
        order.setUpdateTime(new Date());
        order.setCreateTime(new Date());
        Map<String,String> param = new HashMap<>();
        order.setGoodsMsg("线下");
        FastSilverInternal internal = fastSilverInternalRepository.findByUserId(String.valueOf(view.getUserId()));
        if (internal == null) {
            return CommonsUtil.returnError("支付失败，该商户信息不存在");
        }
        String orderNo = view.getOrderNo();
        param.put("money",String.valueOf(view.getMoney()));
        param.put("shopId",internal.getMerchantId());
        param.put("orderId",orderNo);
        String sign = PayUtil.parseSign(param, key);
        String str = "?shopId=" + internal.getMerchantId() + "&orderId="+orderNo + "&money=" + view.getMoney() +
                "&type=" + orderType + "&device=" + order.getDevice() + "&goodsMsg="+
                order.getGoodsMsg() + "&sign=" + sign + "&redirectUrl=" + callbackPayUrl + "&redirectNumber=" + "3";
        String url = payUrl + str;
        logger.info(url);
        RestTemplate restTemplate = new RestTemplate();
        try {
            String result = restTemplate.getForObject(url, String.class);
            logger.debug(result);
            order.setMerchantId(internal.getMerchantId());
            order.setOrderType(OrderType.of(orderType));
            order.setOrderStatus(OrderStatus.PENDING);
            fastSilverRepository.save(order);
            return CommonsUtil.returnSuccess("",result);
        } catch (Exception e) {
            logger.error("fastSilverPay error pram {} error {}" + str + e.getMessage());
            return CommonsUtil.returnError("交易失败"+ e.getMessage());
        }
    }

    @RequestMapping(method= RequestMethod.GET,value="/v1.0/channel/fast_silver/callback")
    public @ResponseBody Object callback(@RequestParam(value = "resultCode") String resultCode,
                                         @RequestParam(value = "outTradeNo") String outTradeNo,
                                         @RequestParam(value = "orderId") String orderNo,
                                         @RequestParam(value = "money") String money,
                                         @RequestParam(value = "type") String type) {
        OrderStatus  orderStatus = OrderStatus.PENDING;
        if (CommonConstants.BASE_SUCCESS.toUpperCase().equals(resultCode.toUpperCase())) {
            orderStatus = OrderStatus.SUCCESS;
            feastSilverBusiness.updateOrderStatus(orderNo,orderStatus,outTradeNo,resultCode);
            FastSilverOrder fa= fastSilverRepository.findByOrderNo(orderNo);
            URI uri = util.getServiceUrl("user", "error url request");
            String url = uri.toString() + "/v1.0/user/jpush/sendPayAsk";
            LinkedMultiValueMap<String,String> requestEntity = new LinkedMultiValueMap<String,String>();
            if(fa==null){
                return CommonsUtil.returnError("推送失败，该商户信息不存在");
            }else{
                String userId=String.valueOf(fa.getUserId());
                requestEntity.add("userId",userId);
                requestEntity.add("money",money);
                requestEntity.add("type",type);
                RestTemplate restTemplate = new RestTemplate();
                String resultString = restTemplate.postForObject(url, requestEntity, String.class);

            }
            return CommonsUtil.returnSuccess("支付成功");


        } else {
            orderStatus = OrderStatus.FAILURE;
            feastSilverBusiness.updateOrderStatus(orderNo,orderStatus,outTradeNo,resultCode);
            return CommonsUtil.returnSuccess("支付失败");
        }
    }

    /**
     * 快银支付宝/微信分页查询
     */
    @RequestMapping(method= RequestMethod.GET,value="/v1.0/channel/fast_silver/order/page")
    public @ResponseBody Object queryFastSilverPage(FastSilverOrderView view, @PageableDefault(size = 20, sort = "id")
            Pageable pageable) {
        Page<FastSilverOrderView> page = feastSilverBusiness.queryFastSilver(view,pageable);
        return CommonsUtil.returnOK(page);
    }

    /**
     * 快银支付宝/微信详细查询
     */
    @RequestMapping(method= RequestMethod.GET,value="/v1.0/channel/fast_silver/order")
    public @ResponseBody Object queryFastSilver(@RequestParam(value = "orderNo")String orderNo) {
        if (hasText(orderNo)) {
           FastSilverOrder order = fastSilverRepository.findByOrderNo(orderNo);
            if (order != null) {
                return CommonsUtil.returnOK(order.transform());
            }
        }
        return CommonsUtil.returnSuccess("成功");
    }

    /**
     * 快银商户进件
     */
    @RequestMapping(method= RequestMethod.POST,value="/v1.0/channel/fast_silver/internal")
    public @ResponseBody Object internal(HttpServletRequest request) {

        Map<String,String[]> requestMap = request.getParameterMap();
        Map<String,String> paramMap = new HashMap<>();
        Iterator<Map.Entry<String, String[]>> it = requestMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, String[]> entry = it.next();
            if (entry.getValue().length == 1) {
                paramMap.put(entry.getKey(), entry.getValue()[0]);
            } else {
                String[] values = entry.getValue();
                String value = "";
                for (int i = 0; i < values.length; i++) {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
                paramMap.put(entry.getKey(), value);
            }
        }
        FastSilverInternalView view = new FastSilverInternalView();
        view.setAgentId(agentId);
        view.toMap(paramMap);
        view.setNotifyUrl(callbackPayUrl);
        Map<String,String> pram = view.addMap();
        String sign = PayUtil.parseSign(pram, key);
        JSONObject json = PayUtil.mapToJson(pram);
        try {
            json.put("sign", sign);
            logger.info("request===" + json.toString());
            String result = HttpConnectionUtil.AccessUrl(internalUrl, json.toString());
            Map<String,String> map =  JSONObject.fromObject(result);
			String resultCode = MapUtils.getString(map,"result_code");
			if(CommonConstants.BASE_SUCCESS.toUpperCase().equals(resultCode.toUpperCase())){
				String shopId = MapUtils.getString(map,"shop_id");
				logger.info("快银注册中，商户号为：" + shopId);
				view.setMerchantId(shopId);
                FastSilverInternal internal = view.transform();
                fastSilverInternalRepository.save(internal);
				return CommonsUtil.returnOK();
			}else{
				String errorMsg = MapUtils.getString(map,"error_msg");
				logger.info("进件失败：" + errorMsg);
                return  CommonsUtil.returnError(errorMsg);
			}
        } catch (Exception e) {
            logger.info("进件异常，{}" + view.toString() + e.getMessage());
            return  CommonsUtil.returnError("进件异常");
        }

    }

    @RequestMapping(method= RequestMethod.POST,value="/v1.0/channel/fast_silver/sy/upload")
    public @ResponseBody Object upload(@RequestParam(value = "userId")String userId) {
        try {
            if (hasText(userId)) {
                Map<String,String> pram = outChannelService.queryUpload(userId);
                FastSilverUpload upload = new FastSilverUpload();
                Map<String,String> map = MapUtils.getMap(pram,"result");
                upload.transform(map);
                FastSilverInternal internal = fastSilverInternalRepository.findByUserId(userId);
                Map<String,String> param = fastSilverUpload( upload, internal.getMerchantId(),internal.getType());
                String resultCode = MapUtils.getString(param,"result_code");
                if(CommonConstants.BASE_SUCCESS.toUpperCase().equals(resultCode.toUpperCase())){
                    return CommonsUtil.returnOK("同步成功");
                }
            }
            return CommonsUtil.returnError("同步成功");
        } catch (Exception e) {
            logger.error("同步数据失败" + e.getMessage());
            return CommonsUtil.returnError("同步数据失败");
        }


    }


    private Map<String, String> fastSilverUpload(FastSilverUpload upload,String merchantId,String type) {
        Map<String, String> textMap = new HashMap<>();
        textMap.put("shop_id", merchantId);
        textMap.put("file_type", "merchantHead");
        Map<String, Object> fileMap = new HashMap<>();
        InputStream pis = PayUtil.getLinkInputStream(upload.getMerchantHead());

        InputStream merchantCheck = PayUtil.getLinkInputStream(upload.getMerchantCheck());
        if (hasText(upload.getOtherPhoto3()) && !"null".equals(upload.getOtherPhoto3())) {
            InputStream otherPhoto3 = PayUtil.getLinkInputStream(upload.getOtherPhoto3());
            fileMap.put("otherPhoto3",otherPhoto3);
        }
        if (hasText(upload.getOtherPhoto4()) && !"null".equals(upload.getOtherPhoto4())) {
            InputStream otherPhoto4 = PayUtil.getLinkInputStream(upload.getOtherPhoto4());
            fileMap.put("otherPhoto4",otherPhoto4);
        }

        if (hasText(upload.getIdentityFaceCopy()) && !"null".equals(upload.getIdentityFaceCopy())) {
            InputStream identityFaceCopy = PayUtil.getLinkInputStream(upload.getIdentityFaceCopy());
            fileMap.put("identityFaceCopy",identityFaceCopy);
        }

        if (hasText(upload.getIdentityBackCopy()) && !"null".equals(upload.getIdentityBackCopy())) {
            InputStream identityBackCopy = PayUtil.getLinkInputStream(upload.getIdentityBackCopy());
            fileMap.put("identityBackCopy",identityBackCopy);
        }

        if (hasText(upload.getOtherPhoto2()) && !upload.getOtherPhoto2().equals("null")) {
            InputStream otherPhoto2 = PayUtil.getLinkInputStream(upload.getOtherPhoto2());
            fileMap.put("otherPhoto2",otherPhoto2);
        }

        if (hasText(upload.getOtherPhoto()) && !upload.getOtherPhoto().equals("null")) {
            InputStream otherPhoto = PayUtil.getLinkInputStream(upload.getOtherPhoto());
            fileMap.put("otherPhoto",otherPhoto);
        }
        fileMap.put("merchantHead",pis);
        fileMap.put("merchantCheck",merchantCheck);

        if (hasText(upload.getCardFace()) && !upload.getCardFace().equals("null")) {
            InputStream cardFace = PayUtil.getLinkInputStream(upload.getCardFace());
            fileMap.put("cardFace",cardFace);
        }
        if (hasText(upload.getIdentityFace()) && !upload.getIdentityFace().equals("null")) {
            InputStream identityFace = PayUtil.getLinkInputStream(upload.getIdentityFace());
            fileMap.put("identityFace",identityFace);
        }
        if (hasText(upload.getIdentityBack()) && !upload.getIdentityBack().equals("null")) {
            InputStream identityBack = PayUtil.getLinkInputStream(upload.getIdentityBack());
            fileMap.put("identityBack",identityBack);
        }
        if (hasText(upload.getBussinessCard()) && !upload.getBussinessCard().equals("null")) {
            InputStream bussinessCard = PayUtil.getLinkInputStream(upload.getBussinessCard());
            fileMap.put("bussinessCard",bussinessCard);
        }
        if (hasText(upload.getBussiness()) && !upload.getBussiness().equals("null")) {
            InputStream bussiness = PayUtil.getLinkInputStream(upload.getBussiness());
            fileMap.put("bussiness",bussiness);
        }
        if (hasText(upload.getIdentityBody()) && !upload.getIdentityBody().equals("null")) {
            InputStream identityBody = PayUtil.getLinkInputStream(upload.getIdentityBody());
            fileMap.put("identityBody",identityBody);
        }

        String result = HttpConnectionUtil.formUpload(uplodUrl, textMap, fileMap, "image/png");
        logger.info(result);
        Map<String,String> map =  JSONObject.fromObject(result);
        String resultCode = MapUtils.getString(map,"result_code");
        if(CommonConstants.BASE_SUCCESS.toUpperCase().equals(resultCode.toUpperCase())){
            String str = MapUtils.getString(map,"list");
            String[] string = str.split(",");
        }else{
            logger.info("进件失败，原因为：" + MapUtils.getString(map,"error_msg"));
            throw new RuntimeException("进件失败");
        }
        return map;
    }

    @Scheduled(cron = "0 0/20 * * * ?")
    public void synLoginStatus() {
        List<FastSilverInternal> list = fastSilverInternalRepository.findByStatus(LoginStatus.PENDING);
        if (list.size() > 0) {
            for (FastSilverInternal internal : list) {
                Map<String, String> textMap = new HashMap<>();
                Map<String,String> pram = new HashMap<> ();
                pram.put("shop_id",internal.getMerchantId());
                String sign = PayUtil.parseSign(pram, key);
                textMap.put("shop_id", internal.getMerchantId());
                textMap.put("sign", sign);
                logger.info("request===" + textMap.toString());
                String result = HttpConnectionUtil.AccessUrl(queryInternalUrl, textMap.toString());
                Map<String,String> map =  JSONObject.fromObject(result);
                String resultCode = MapUtils.getString(map,"result_code");
                String errorMsg = MapUtils.getString(map,"error_msg");
                if (CommonConstants.BASE_SUCCESS.toUpperCase().equals(resultCode.toUpperCase())) {
                    internal.setStatus(LoginStatus.SUCCESS);
                } else if (resultCode.toUpperCase().equals(LoginStatus.FAIL.getValue().toUpperCase())){
                    internal.setStatus(LoginStatus.FAIL);
                    internal.setErrorMsg(errorMsg);
                }
            }
            fastSilverInternalRepository.save(list);
        }

    }

    /**
     * 查询商户进件信息同步信息
     */
    @RequestMapping(method= RequestMethod.GET,value="/v1.0/channel/fast_silver/searchmerchantmsg")
    public @ResponseBody Object searchmerchantmsg(@RequestParam(value = "merchantId",required = false) String merchantId,
                                                  @RequestParam(value = "phone",required = false) String phone,
                                                  @RequestParam(value = "page", defaultValue = "0", required = false) int page,
                                                  @RequestParam(value = "size", defaultValue = "20", required = false) int size,
                                                  @RequestParam(value = "order", defaultValue = "DESC", required = false) Sort.Direction direction,
                                                  @RequestParam(value = "sort", defaultValue = "createTime", required = false) String sortProperty
    ) {
        String userId = "";
        Pageable pageable = new PageRequest(page, size, new Sort(direction, sortProperty));
        if (hasText(phone)) {
            Map<String,String> param = outChannelService.queryUser(phone);
            userId = MapUtils.getString(param,"id");
        }

        try {
            List<FastSilverInternal> list = feastSilverBusiness.queryInternal(userId,merchantId,pageable);
            List<FastSilverInternal> listCount = feastSilverBusiness.queryInternalcount(userId,merchantId);
            if (list.size() < 1) {
                if (hasText(merchantId)) {
                    FastSilverInternalView view = new FastSilverInternalView();
                    Map<String, String> textMap = new HashMap<>();
                    Map<String,String> pram = new HashMap<> ();
                    pram.put("shop_id",merchantId);
                    String sign = PayUtil.parseSign(pram, key);
                    textMap.put("shop_id", merchantId);
                    textMap.put("sign", sign);
                    logger.info("request===" + textMap.toString());
                    String result = HttpConnectionUtil.AccessUrl(queryInternalUrl, textMap.toString());
                    view.setUserId(userId);
                    view.setMerchantId(merchantId);
                    Map<String,String> map =  JSONObject.fromObject(result);
                    String resultCode = MapUtils.getString(map,"result_code");
                    if(CommonConstants.BASE_SUCCESS.toUpperCase().equals(resultCode.toUpperCase())){
                        view.addMap(map);
                        FastSilverInternal internal = view.transform();
                        fastSilverInternalRepository.save(internal);
                        view.transform(internal);
                        List<FastSilverInternalView> views = new ArrayList<>();
                        return CommonsUtil.returnOK(new PageImpl<>(views, pageable, views.size()));
                    }else{
                        String errorMsg = MapUtils.getString(map,"error_msg");
                        logger.info("同步进件信息失败：" + errorMsg);
                        return  CommonsUtil.returnError("该商户未进件");
                    }
                }
                return CommonsUtil.returnError("没有商户信息");
            } else {
                List<FastSilverInternalView> result = new ArrayList<>();
                for (FastSilverInternal fastSilverInternal : list) {
                    FastSilverInternalView view = new FastSilverInternalView();
                    view.transform(fastSilverInternal);
                    result.add(view);
                }

                return CommonsUtil.returnSuccess("查询成功",new PageImpl<>(result, pageable, listCount.size()));
            }
        } catch (Exception e) {
            logger.error("该商户未进件，需绑定台码进行进件" + e.getMessage());
            return CommonsUtil.returnError("该商户未进件，请绑定台码进行进件" + e.getMessage());
        }
    }

    /**
     * 商户进件
     */
    @RequestMapping(method= RequestMethod.GET,value="/v1.0/channel/fast_silver/query/internal")
    public @ResponseBody Object queryInternal(String userId) {
        FastSilverInternal internal = fastSilverInternalRepository.findByUserId(userId);
        return CommonsUtil.returnOK(internal);
    }

    /**
     * 同步扫码订单状态
     * @param orderNo 订单号
     * @param userId 商户id
     * @return
     */
    @RequestMapping(method= RequestMethod.GET,value="/v1.0/channel/fast_silver/syn_order")
    public @ResponseBody Object synOrder(
            @RequestParam(value = "orderNo") String orderNo,
            @RequestParam(value = "userId") String userId) {
        try {
            FastSilverOrder order = fastSilverRepository.findByOrderNo(orderNo);
            if (order == null) {
                return CommonsUtil.returnError("该订单号不存在");
            }
            return syn( userId, orderNo,order);
        } catch (Exception e) {
            logger.error("同步状态异常" + e.getMessage());
            return CommonsUtil.returnError("同步状态失败！");
        }
    }

    private Object syn(String userId,String orderNo,FastSilverOrder order) {
        FastSilverInternal internal = fastSilverInternalRepository.findByUserId(userId);
        String url = queryOrderUrl +"?orderId=" + orderNo + "&shopId=" + internal.getMerchantId();
        logger.info(url);
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForObject(url, String.class);
        Map<String,String> pram = JSONObject.fromObject(result);
        String resultCoe = MapUtils.getString(pram,"result_code");
        if (resultCoe.toUpperCase().equals(CommonConstants.BASE_SUCCESS.toUpperCase())) {
            int status = MapUtils.getInteger(pram, "status");
            String cmOrderId = MapUtils.getString(pram, "cmOrderId");
            order.setTransactiNo(cmOrderId);
            if (status == 1) {
                order.setOrderStatus(OrderStatus.SUCCESS);
            } else if (status == 0 || status == 3) {
                order.setOrderStatus(OrderStatus.FAILURE);
            } else if (status == 2) {
                order.setOrderStatus(OrderStatus.PENDING);
            }
            fastSilverRepository.save(order);
            outChannelService.synMerchant(orderNo, status);
            return CommonsUtil.returnOK();
        } else {
            return CommonsUtil.returnError("订单信息不存在，请确认");
        }
    }


    /**
     * 3分钟同步一次订单信息
     */
    @Scheduled(cron = "0 0/3 * * * ?")
    public void queryAndUpdateCJJob() {
        if ("true".equals(scheduleTaskOnOff)) {
            logger.info("=========开始：获取所有处在支付中的交易记录，并更新交易记录表状态JOB=========");
            Calendar beforeTime = Calendar.getInstance();
            beforeTime.add(Calendar.MINUTE, -3);// 3分钟之前的时间
            Date beforeD = beforeTime.getTime();
            List<FastSilverOrder> list = fastSilverRepository.findByOrderList(OrderStatus.PENDING,beforeD);
            for (FastSilverOrder order : list) {
                syn( String.valueOf(order.getUserId()), order.getOrderNo(), order);
            }
            logger.info("=========结束：获取所有处在支付中的交易记录，并更新交易记录表状态JOB=========");
        }
    }

    @RequestMapping(method= RequestMethod.GET,value="/v1.0/channel/fast_silver/syn_status")
    public @ResponseBody Object synOrderStatus(
                @RequestParam(value = "orderNo")String str) {
        List<String> list = Arrays.asList(str.split(","));
        List<FastSilverOrder> result = fastSilverRepository.findByOrderNoIn(list);
        return result;
    }
}
